package biz

import (
	"context"
	"time"

	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/kycadminrepo"
	"git.bybit.com/svc/go/pkg/bstd"
	"git.bybit.com/svc/go/pkg/bzap"
	"go.elastic.co/apm"
	"go.uber.org/zap"
)

type Handler struct {
	*Environment

	method     string
	startTime  time.Time
	cancel     context.CancelFunc
	span       *apm.Span
	finalizers []finalizer
	logger     *zap.Logger
}

type finalizer struct {
	bstd.Job
	message string
}

func (env *Environment) CreateHandlerWithTimeout(ctx context.Context, method string, timeout time.Duration) *Handler {
	ctx, cancel := bzap.TracedTimeoutContext(ctx, timeout)
	span, ctx := apm.StartSpan(ctx, "service", "cust")
	env.CancelWG().Add(1)

	hdl := &Handler{
		Environment: env.WithContext(ctx),
		method:      method,
		startTime:   time.Now(),
		cancel:      cancel,
		span:        span,
		finalizers:  []finalizer{},
		logger:      env.Logger(),
	}

	return hdl
}

func (h *Handler) Dispose() {
	for _, finalizer := range h.finalizers {
		bzap.LogError(h.LoggerWithCtx(), finalizer.message, finalizer.Job())
	}
	if h.cancel != nil {
		h.cancel()
	}
	if h.span != nil {
		h.span.End()
		h.handleTimeSummary(h.method).Observe(time.Since(h.startTime).Seconds())
	}

	h.CancelWG().Done()
}

func (h *Handler) StartTime() time.Time {
	return h.startTime
}

func (h *Handler) KycAdminRepo() KycAdminRepo {
	return kycadminrepo.New(h.Logger(), h.ChtKycDB(), h.UserDB(), h.SecHub(), h.Teller(),
		h.KycSvc(), h.InternalDataKey(), h.Kafka())
}

func (h *Handler) Logger() *zap.Logger {
	return h.logger
}
